<template>
  <n-popover placement="bottom" :trigger="props.trigger">
    <template #trigger>
      <slot :iconName="state.selectedIcon">
        <n-button :size="props.size" v-bind="$attrs">
          <template #icon>
            <icons
              v-if="state.selectedIcon !== ''"
              :name="state.selectedIcon"
            />
          </template>
          图标选择器
        </n-button>
      </slot>
    </template>
    <div class="pro-icon-select-container">
      <div class="icon-header-container">
        <n-grid :x-gap="22" :y-gap="8" cols="1" responsive="screen">
          <n-gi>
            <n-space>
              <n-input
                v-model:value="searchText"
                placeholder="请输入图标名称"
                :size="props.size"
                clearable
              />
              <n-button
                type="warning"
                :size="props.size"
                ghost
                @click="handleReset"
              >
                重置
              </n-button>
            </n-space>
          </n-gi>
        </n-grid>
      </div>
      <div class="icon-list-container" v-loading="state.loading">
        <n-grid :x-gap="14" :y-gap="8" :cols="props.col" responsive="screen">
          <n-gi
            v-for="icon in data.dataList"
            :key="`${icon.name}${icon.title}`"
          >
            <n-card
              hoverable
              class="icon-card"
              :class="{ checked: state.selectedIcon === icon.name }"
              @click="changeIcon(icon)"
            >
              <div class="icon-container">
                <icons :name="icon.name" size="22" />
              </div>
            </n-card>
          </n-gi>
        </n-grid>
        <n-pagination
          v-model:page="state.pageArg.currentPage"
          v-model:page-size="state.pageArg.pageSize"
          :page-slot="5"
          :size="props.size"
          class="list-pagination"
          :item-count="data.total"
        />
      </div>
    </div>
  </n-popover>
</template>
<script lang="ts" setup name="proIconSelect">
  import iconMap from '@icon-park/vue-next/icons.json'
  const svgFiles = import.meta.glob('/src/assets/svg/*.svg')

  const props = defineProps({
    trigger: {
      type: String,
      default: 'click'
    },
    value: {
      type: String,
      default: ''
    },
    // 一行排列的图标个数
    col: {
      type: Number,
      default: 4
    },
    size: {
      type: String,
      default: 'medium'
    },
    // 一页显示的图标个数
    pageSize: { type: Number, default: 16 }
  })

  const emits = defineEmits(['update:value', 'change'])

  enum ICON_OPTIONS {
    ICON_PARK = 'iconPark',
    SVG_ICON = 'svgIcon'
  }

  const defaultPage = {
    currentPage: 1,
    pageSize: props.pageSize
  }

  const state = reactive({
    pageArg: { ...defaultPage },
    loading: true,
    selectedIcon: '',
    iconSearch: (v) => v
  })

  const searchText = ref('')

  const iconPark = {
    type: ICON_OPTIONS.ICON_PARK,
    list: iconMap.map((icon) => ({
      title: icon.title,
      name: `i-${icon.name}`
    })),
    total: iconMap.length
  }

  const svgIcon = {
    type: ICON_OPTIONS.SVG_ICON,
    list: Object.keys(svgFiles).map((icon) => {
      const title = icon.replace('/src/assets/svg/', '').replace(/.svg$/, '')
      return {
        name: `icon-${title}`,
        title
      }
    }),
    total: Object.keys(svgFiles).length
  }

  const iconList = [...iconPark.list, ...svgIcon.list]

  const data = computed(() => {
    state.loading = true

    const { currentPage, pageSize } = state.pageArg
    const list = state.iconSearch(iconList || [])

    nextTick(() => {
      state.loading = false
    })

    return list
      ? {
          dataList: list.slice(
            (currentPage - 1) * pageSize,
            currentPage * pageSize
          ),
          total: list.length
        }
      : { dataList: [], total: 0 }
  })

  // 分页重置
  const resetPage = () => {
    Object.assign(state.pageArg, { ...defaultPage, pageSize: props.pageSize })
  }

  // 搜索
  watch(searchText, () => {
    state.iconSearch = (list) => {
      return list.filter(
        (icon) =>
          new RegExp(searchText.value).test(icon.name) ||
          new RegExp(searchText.value).test(icon.title)
      )
    }
    resetPage()
  })

  const handleReset = () => {
    searchText.value = ''
    changeIcon({ name: '' })
    resetPage()
  }

  watch(
    () => props.value,
    (v) => {
      state.selectedIcon = v
    },
    {
      immediate: true
    }
  )

  watch(
    () => props.pageSize,
    () => {
      resetPage()
    }
  )

  const changeIcon = (icon) => {
    state.selectedIcon = icon.name
    emits('update:value', icon.name)
    emits('change', icon.name)
  }
</script>

<style lang="less" scoped>
  .pro-icon-select-container {
    padding: 10px;
    .icon-header-container {
      :deep(.n-input) {
        flex: 1;
      }
    }
    .icon-list-container {
      margin-top: 15px;
      .icon-card {
        cursor: pointer;
        &.checked {
          border-color: var(--primary-color);
          box-shadow: var(--primary-color-alpha) 0px 3px 8px;
        }
      }
      .icon-container {
        text-align: center;
      }
      .list-pagination {
        margin-top: 15px;
        justify-content: center;
      }
      :deep(.n-card__content) {
        padding: 5px !important;
      }
    }
  }
</style>
